package com.wjk.kylin.modules.system.menu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wjk.kylin.core.utils.SecurityUtils;
import com.wjk.kylin.modules.system.role.service.IRoleMenuService;
import com.wjk.kylin.modules.system.vo.MetaVO;
import com.wjk.kylin.modules.system.vo.RouterVO;
import com.wjk.kylin.modules.system.menu.entity.Menu;
import com.wjk.kylin.modules.system.menu.mapper.MenuMapper;
import com.wjk.kylin.modules.system.menu.service.IMenuService;
import com.wjk.kylin.modules.system.user.entity.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 *  角色表 服务实现类
 * </p>
 *
 * @author wangjkui
 * @since 2020-06-01
 */
@Service
@Transactional(readOnly=true)
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
    @Autowired
    private IRoleMenuService roleMenuService;

    @Override
    @Transactional(readOnly=false)
    public boolean save(Menu menu) {
        menu.preInsert();
        return super.save(menu);
    }

    @Override
    @Transactional(readOnly=false)
    public boolean update(Menu menu) {
        menu.preUpdate();
        return super.updateById(menu);
    }

    @Override
    public boolean hasChildByMenuId(String menuId) {
        QueryWrapper<Menu> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", menuId);
        int count = this.count(wrapper);
        if(count > 0){
           return true;
        }
        return false;
    }

    @Override
    @Transactional(readOnly=false)
    public boolean deleteById(String menuId) {
        //1.删除角色菜单关联数据
        roleMenuService.deleteByMenuIds(Arrays.asList(menuId));

        return super.removeById(menuId);
    }

    @Override
    public Collection<SimpleGrantedAuthority> findMenuPermsByUser(User user) {
        List<String> list = new ArrayList<>();
        Collection<SimpleGrantedAuthority> permsSet = new HashSet<>();
        // 管理员拥有所有权限
        if (user.isAdmin()) {
            list = baseMapper.findAllMenuPermsList();
        } else {
            list = baseMapper.findMenuPermsByUserId(user.getId());
        }

        list.forEach(l->{
            if (StringUtils.isNotBlank(l)) {
                permsSet.add(new SimpleGrantedAuthority(l));
            }
        });

        return permsSet;
    }

    @Override
    public Set<String> findMenuPermsByUserToUser(User user) {
        List<String> list = new ArrayList<>();
        Set<String> permsSet = new HashSet<>();
        // 管理员拥有所有权限
        if (user.isAdmin()) {
            list.add("*:*:*");
        } else {
            list = baseMapper.findMenuPermsByUserId(user.getId());
        }

        list.forEach(l->{
            if (StringUtils.isNotBlank(l)) {
                permsSet.add(l);
            }
        });

        return permsSet;
    }

    @Override
    public List<Menu> treeList() {
        return listWithTree(super.list(),"0");
    }

    @Override
    public List<RouterVO> getRouters(String userId) {
        List<Menu> menus = findMenuTreeByUserId(userId);

        List<RouterVO> list = buildMenus(menus);

        return list;
    }

    /**
     * 菜单集合
     * @param userId
     * @return
     */
    public List<Menu> findMenuTreeByUserId(String userId) {
        List<Menu> menus = new ArrayList<>();
        if (SecurityUtils.isAdmin(userId)) {
            menus = baseMapper.findMenuTreeAll();
        } else {
            menus = baseMapper.findMenuTreeByUserId(userId);
        }
        return listWithTree(menus,"0");
    }

    /**
     * 获取路由 根据菜单
     * @param menus
     * @return
     */
    public List<RouterVO> buildMenus(List<Menu> menus) {
        List<RouterVO> routers = new LinkedList<>();
        for (Menu menu : menus) {
            RouterVO router = new RouterVO();

            router.setHidden("1".equals(menu.getVisible()));//1:隐藏

            router.setName(StringUtils.capitalize(menu.getPath()));//首字母大写
            router.setPath(getRouterPath(menu));//获取路由地址
            router.setComponent(StringUtils.isEmpty(menu.getComponent()) ? "Layout" : menu.getComponent());
            router.setMeta(new MetaVO(menu.getName(), menu.getIcon()));

            List<Menu> cMenus = menu.getChildren();
            if (!cMenus.isEmpty() && cMenus.size() > 0 && "M".equals(menu.getMenuType())) {
                router.setAlwaysShow(true);
                router.setRedirect("noRedirect");
                router.setChildren(buildMenus(cMenus));
            }
            routers.add(router);
        }
        return routers;
    }


    /**
     * 获取路由地址
     *
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(Menu menu) {
        String routerPath = menu.getPath();
        // 非外链并且是一级目录                     是否为外链（1是 0否）
        if ("0".equals(menu.getParentId()) && "0".equals(menu.getFrameFlag())) {
            routerPath = "/" + menu.getPath();
        }
        return routerPath;
    }

    /**
     * 组装成父子的树形结构
     * @param all
     * @return
     */
    public List<Menu> listWithTree(List<Menu> all,String parentId) {
        List<Menu> rootList = all.stream().filter(menu ->
                menu.getParentId().equals(parentId)
            ).map(menu->{
                menu.setChildren(listWithTree(all,menu.getId()));
                return menu;
            }).sorted(Comparator.comparing(Menu::getSort))
            .collect(Collectors.toList());
        return rootList;
    }

}
